/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package jtplugin;

/**
 *
 * @author christoph
 */
public class TTTGameLogic {
    private static int SYMBOL_X = 1;
    private static int SYMBOL_O = 2;
    private static int EMPTY = 0;
    private int userPlaying = SYMBOL_X;
    private int enemyPlaying = SYMBOL_O;

    private int gamesArea[] = {EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY};
    private String winCombinations[] = {"123", "456", "789", "147", "258", "369", "159", "357"};

    private static int ENEMY_REMOTE = 0;
    private static int ENEMY_AI = 1;
    private int enemyType = 1;

    private TTTWindow myGameWindow;
    private boolean waitingForUser = true;
    private int aIQuality = 0;

    private boolean gameEnds = false;
    public String lastWinCombi;

    public TTTGameLogic(TTTWindow _gameWindow) {
        this.myGameWindow = _gameWindow;        
    }

    public void startGame(boolean _userBegins, int _userSymbol, int _enemyType, int _aIQuality) {
        System.out.println("----> in TTTGameLogic.startGame()");

        this.lastWinCombi = "";
        this.enemyType = _enemyType;
        this.userPlaying = _userSymbol;
        
        if(this.userPlaying == SYMBOL_X)
            this.enemyPlaying = SYMBOL_O;
        else
            this.enemyPlaying = SYMBOL_X;

        this.aIQuality = _aIQuality;
        this.gameEnds = false;

        for(int i=1; i<10; i++) {
            this.gamesArea[i-1] = EMPTY;
            this.myGameWindow.setSymbolOnButton(i, EMPTY);
        }

        if(this.enemyType == ENEMY_AI)
            System.out.println("AI quality: " + this.aIQuality);

        if(_userSymbol == SYMBOL_O)
            this.enemyPlaying = SYMBOL_X;

        this.waitingForUser = _userBegins;

        if(_userBegins)
            this.setGameStatusString("Waiting for LOCAL...");
        else
            this.setGameStatusString("Waiting for ENEMY...");

        System.out.println("Starting GAME...");
         for(int i=1; i<10; i++)
            this.myGameWindow.setSymbolOnButton(i, EMPTY);

        if(!this.waitingForUser && this.enemyType == ENEMY_AI) {
            System.out.println("AI");
            this.AITurn(true);
        }
    }

    public void cancelGame() {
        for(int i=1; i<10; i++)
            this.myGameWindow.setSymbolOnButton(i, EMPTY);

        this.gameEnds = true;
    }

    public boolean checkForGamesEnd() {
        int winner = this.checkFieldForWinner();
        if(winner > 0) {
            // GAME ENDS HERE - we have a winner
            if(winner == this.userPlaying) {
                this.myGameWindow.gameEnds(0);
            } else {
                this.myGameWindow.gameEnds(1);
            }

            return true;
        } else if(winner == -2) {
            // // GAME ENDS HERE - Tied
            this.myGameWindow.gameEnds(-1);
            return true;
        }

        return false;
    }

    public boolean userAction(int _index) {
        if(this.gameEnds) {
            this.setGameStatusString("Start a new game first!");
            return false;
        }
        
        if(!this.waitingForUser) {
            this.setGameStatusString("It's not yor turn! Wait for ENEMY.");
            return false;
        }

        if(this.gamesArea[_index-1] == EMPTY) {
            this.gamesArea[_index - 1] = this.userPlaying;
            this.myGameWindow.setSymbolOnButton(_index, this.userPlaying);            
        } else {
            this.setGameStatusString("Allready used - choose another field!");
            return false;
        }

        this.waitingForUser = false;

        if(this.checkForGamesEnd())
            return true;

        this.setGameStatusString("Waiting for ENEMY...");

        if(this.enemyType == ENEMY_AI) {            
            this.AITurn(false);

            if(this.checkForGamesEnd())
                return true;
        }

        return true;
    }
    
    private int checkFieldForWinner() {
        int checkSymbol = SYMBOL_X;

        for(int j=0; j<2; j++) {
            for(int i=0; i<this.winCombinations.length; i++ ) {
                if(this.getWinCombinationField(i, 0) == checkSymbol &&
                   this.getWinCombinationField(i, 1) == checkSymbol &&
                   this.getWinCombinationField(i, 2) == checkSymbol) {

                   System.out.println("WINNER!");
                   this.lastWinCombi = this.winCombinations[i];
                   this.setGameStatusString("The winner is: " + this.myGameWindow.symbols[checkSymbol]);
                   this.gameEnds = true;
                   return checkSymbol;
                }
            }
            checkSymbol = SYMBOL_O;
        }

        // No winner now - check for full game area
        for(int k=0; k<this.gamesArea.length; k++) {
            if(this.gamesArea[k] == EMPTY) {
                return -1;
            }
        }

        // No empty field found - end game tied
        this.setGameStatusString("Tied");
        return -2;
    }

    private void setGameStatusString(String _status) {
        this.myGameWindow.setStatusString(_status);
    }

    private int getWinCombinationField(int _combi, int _field) {
        return this.gamesArea[Integer.parseInt(
                    this.winCombinations[_combi].substring(_field,_field+1))-1];
    }

    private int getWinCombinationFieldIndex(int _combi, int _field) {
        return Integer.parseInt(this.winCombinations[_combi].substring(_field,_field+1));
    }

    public boolean externalAction(int _index) {
        if(this.waitingForUser)
            return false;

        if(this.gamesArea[_index-1] == EMPTY) {
            this.gamesArea[_index - 1] = this.enemyPlaying;
            this.myGameWindow.setSymbolOnButton(_index, this.enemyPlaying);
            this.waitingForUser = true;

            if(this.checkForGamesEnd())
                return true;
            
            this.setGameStatusString("Waiting for YOU...");
            return true;
        }

        return false;
    }

    private void AITurn(boolean _firstTurn) {
        if(_firstTurn) {
            if(this.externalAction(5))
                return;
        }
        
        int sum = 0;
        int content = EMPTY;
        int empty = -1;

        // Search for a win combi
        if(this.aIQuality < 2) {

            for(int i=0; i<this.winCombinations.length; i++ ) {
                for(int j=0; j<3; j++) {
                    content = this.getWinCombinationField(i, j) ;
                    if(content == this.enemyPlaying)
                        sum++;
                    if(content == EMPTY)
                        empty = j;
                }

                if(sum > 1 && empty >= 0) {
                    // Use a free posible combination
                    System.out.println("AI found a winner combi: " + i + ", empty:" + this.getWinCombinationFieldIndex(i, empty));
                    if(this.externalAction(this.getWinCombinationFieldIndex(i, empty)))
                        return;

                } else {
                    sum = 0;
                    empty = -1;
                }
            }
        }

        // Check for some defense need
        sum = 0;
        content = EMPTY;
        empty = -1;
        for(int i=0; i<this.winCombinations.length; i++ ) {
            for(int j=0; j<3; j++) {
                content = this.getWinCombinationField(i, j) ;
                if(content == this.userPlaying)
                    sum++;
                if(content == EMPTY)
                    empty = j;
            }

            if(sum > 1 && empty >= 0) {
                // We must block!
                System.out.println("AI is blocking. combi: " + i + ", empty:" + this.getWinCombinationFieldIndex(i, empty));
                if(this.externalAction(this.getWinCombinationFieldIndex(i, empty)))
                    return;

            } else {
                sum = 0;
                empty = -1;
            }
        }

        // Now use the own chance...
        if(this.aIQuality == 0) {
            sum = 0;
            content = EMPTY;
            empty = -1;
            for(int i=0; i<this.winCombinations.length; i++ ) {
                for(int j=0; j<3; j++) {
                    content = this.getWinCombinationField(i, j) ;
                    if(content == this.enemyPlaying)
                        sum++;
                    if(content == EMPTY)
                        empty = j;
                    if(content == this.userPlaying)
                        sum--;
                }

                if(sum > 0 && empty >= 0) {
                    // Use a free posible combination
                    System.out.println("AI found a combi: " + i + ", empty:" + this.getWinCombinationFieldIndex(i, empty));
                    if(this.externalAction(this.getWinCombinationFieldIndex(i, empty)))
                        return;

                } else {
                    sum = 0;
                    empty = -1;
                }
            }
        }

        // Still no good turn - use the middle field
        if(this.gamesArea[4] == EMPTY) {
            System.out.println("AI has no better idea than using the fild in the middle.");
            this.externalAction(4+1);
            return;
        }

        // Find next free field
        for(int k=0; k<this.gamesArea.length; k++) {            
            if(this.gamesArea[k] == EMPTY) {
                System.out.println("AI has no better idea than using the next free field.");
                this.externalAction(k+1);
                return;
            }
        }
    }
}
